/*
 * Copyright (C) 2009 M. Hautle.
 * 
 * This file is part of TrackedBean.
 * 
 * TrackedBean is free software: you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free
 * Software Foundation, either version 3 of the License, or (at your option) any later version.
 * 
 * TrackedBean is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License along with TrackedBean. If not, see <http://www.gnu.org/licenses/>.
 */
package ch.trackedbean.internal;

import java.util.*;
import java.util.concurrent.*;
import org.eclipse.core.runtime.*;
import org.osgi.framework.*;
import ch.trackedbean.internal.weaving.*;

/**
 * Activator for the OSGi version of TrackedBean.
 * 
 * @author M. Hautle
 * @since 01.10.2010
 */
public class TrackedBeanActivator implements BundleActivator, IRegistryEventListener {
    /** The ID of our weaving extension point. */
    private static final String POINT_ID = "ch.trackedbean.weaving";

    /** The currently active {@link ITrackedBeanWeavingService}s. */
    private final Map<String, ServiceRegistration> services = new ConcurrentHashMap<String, ServiceRegistration>();

    /** The bundle context. */
    private BundleContext ctx;

    /** The platform log. */
    private ILog log;

    /**
     * {@inheritDoc}
     */
    @Override
    public void start(BundleContext context) throws Exception {
        ctx = context;
        log = Platform.getLog(context.getBundle());
        OSGiServiceHelper.start(context);
        LoaderListSericeTracker.start(context);
        // check for our framework extension
        // if (Platform.getBundle("ch.trackedbean.weaving") == null) {
        // log.log(new Status(IStatus.INFO, context.getBundle().getSymbolicName(), "Weaving disabled - ch.trackedbean.weaving is not loaded"));
        // return;
        // }
        final IExtensionPoint ex = Platform.getExtensionRegistry().getExtensionPoint(POINT_ID);
        register(ex.getConfigurationElements());
        Platform.getExtensionRegistry().addListener(this, POINT_ID);
    }

    /**
     * Registers all {@link ITrackedBeanWeavingService}s for the given extension elements.
     * 
     * @param elements the extension elements
     */
    private void register(IConfigurationElement[] elements) {
        for (IConfigurationElement el : elements) {
            final String name = el.getContributor().getName();
            try {
                final String marker = el.getAttribute("markerInteface");
                final MarkerInterfaceWeaver s = new MarkerInterfaceWeaver(name, marker);
                services.put(name, ctx.registerService(ITrackedBeanWeavingService.class.getName(), s, null));
            } catch (Exception e) {
                log.log(new Status(IStatus.ERROR, name, "Error while setting up the weaving service for " + name, e));
            }
        }
    }

    /**
     * Unregisters all {@link ITrackedBeanWeavingService}s for the given extension elements.
     * 
     * @param elements the extension elements
     */
    private void unregister(IConfigurationElement[] elements) {
        for (IConfigurationElement el : elements) {
            final String name = el.getContributor().getName();
            try {
                final ServiceRegistration s = services.remove(name);
                if (s != null)
                    s.unregister();
            } catch (Exception e) {
                log.log(new Status(IStatus.ERROR, name, "Error while unregistering the weaving service for " + name, e));
            }
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void stop(BundleContext context) throws Exception {
        Platform.getExtensionRegistry().removeListener(this);
        // unregister the services
        for (ServiceRegistration s : services.values())
            s.unregister();
        services.clear();
        OSGiServiceHelper.stop();
        LoaderListSericeTracker.stop();
        log = null;
        ctx = null;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removed(IExtension[] extensions) {
        for (IExtension e : extensions)
            unregister(e.getConfigurationElements());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void added(IExtension[] extensions) {
        for (IExtension e : extensions)
            register(e.getConfigurationElements());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void added(IExtensionPoint[] extensionPoints) {
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void removed(IExtensionPoint[] extensionPoints) {
    }
}
